{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from numpy import linalg as npl #J equiv: LinearAlgebra\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.1 Norm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Properties:\n",
    "1. Nonnegative Homogeneity: ||Bx|| = |B|||x||\n",
    "2. Triangle inequality: ||x+y|| <= ||x|| + ||y||\n",
    "3. Nonnegative: ||x|| >= 0\n",
    "4. Definite: ||x|| = 0 iff x = 0 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.0, 3.0, 3.0)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Nonnegative homogeneity: ||Bx|| = |B|||x||\n",
    "x = [2,-1,2]\n",
    "npl.norm(x), np.sqrt(np.inner(x,x)), np.sqrt(sum(np.array(x)**2))\n",
    "#norm(x),sqrt(x'*x),sqrt(sum(x.^2)) <- J equivs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.9291655649341766, 5.242378459855393)"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Triangle inequality: ||x+y|| <= ||x|| + ||y||\n",
    "x,y = np.random.randn(10), np.random.randn(10)\n",
    "npl.norm(x+y), npl.norm(x) + npl.norm(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-0.04252943783238685,\n",
       " 1.0837556422598,\n",
       " array([ 1.        ,  0.7772451 ,  0.55076804,  0.32325192,  0.09735649,\n",
       "        -0.12431346, -0.33923878, -0.54501537, -0.739382  , -0.92024623,\n",
       "        -1.08570801, -1.23408086, -1.36391021, -1.47398886, -1.56336921,\n",
       "        -1.6313723 , -1.67759342, -1.70190437, -1.7044522 , -1.68565468,\n",
       "        -1.64619233, -1.58699731, -1.50923924, -1.41430817, -1.30379488,\n",
       "        -1.17946882, -1.04325395, -0.8972028 , -0.74346905, -0.58427899,\n",
       "        -0.42190233, -0.25862246, -0.09670686,  0.06162219,  0.21421621,\n",
       "         0.35902793,  0.49413741,  0.61777625,  0.7283499 ,  0.82445752,\n",
       "         0.90490937,  0.96874134,  1.01522657,  1.04388392,  1.05448331,\n",
       "         1.04704772,  1.02185198,  0.97941823,  0.92050825,  0.84611263,\n",
       "         0.75743703,  0.65588565,  0.54304213,  0.42064812,  0.2905798 ,\n",
       "         0.15482271,  0.01544505, -0.12543001, -0.26565282, -0.40307609,\n",
       "        -0.53558374, -0.66111939, -0.7777141 , -0.88351311, -0.97680105,\n",
       "        -1.05602551, -1.11981852, -1.16701567, -1.19667275, -1.20807953,\n",
       "        -1.20077059, -1.17453306, -1.12941109, -1.06570712, -0.98397969,\n",
       "        -0.88503813, -0.76993387, -0.63994866, -0.49657978, -0.34152243,\n",
       "        -0.17664947, -0.00398877,  0.17430149,  0.35595938,  0.53864726,\n",
       "         0.71998091,  0.8975595 ,  1.06899594,  1.23194728,  1.38414475,\n",
       "         1.5234231 ,  1.64774887,  1.7552472 ,  1.84422684,  1.91320317,\n",
       "         1.9609187 ,  1.986361  ,  1.98877774,  1.9676886 ,  1.922894  ,\n",
       "         1.85448038]))"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Root Mean Square like norm but within sqrt divide by amount of values in vector\n",
    "#Gives a standard value for magnitude to compare to other vectors\n",
    "#what a \"typical\" value for abs(xi) would be\n",
    "rms = lambda x: npl.norm(x) / np.sqrt(len(x))\n",
    "t = np.linspace(0,1,101) #t = 0:.01:1\n",
    "x = np.cos(8*t) - 2*np.sin(11*t)\n",
    "np.average(x), rms(x), x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1193cb668>"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(t,x) #some signal\n",
    "plt.plot(t, np.average(x)*np.ones(len(x))) #average of the signal:yellow\n",
    "plt.plot(t, (np.average(x)+rms(x))*np.ones(len(x))) #average + rms:green\n",
    "plt.plot(t, (np.average(x)-rms(x))*np.ones(len(x))) #average - rms:red\n",
    "plt.legend(('signal','signal avg', 'avg + rms', 'avg - rms'),\n",
    "           loc='upper left')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(79.0, 101, 20)"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Chebyshev's gives an upper bound for \n",
    "#how many of some value would be expected in a vector\n",
    "cheb_bound = lambda x,a: npl.norm(x)**2//a\n",
    "a = 1.5\n",
    "#where x is the array producing the signal above:\n",
    "cheb_bound(x,a), len(x), len([i for i in x if np.abs(i)>=a]) #*J Companion gets actual with:  sum([1 for i in x if np.abs(i) >= a])\n",
    "#This says there can be *at most*:\n",
    "#79 of the 101 values in x, with an absolute value of at least 1.5\n",
    "#in fact, there are 20"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.2 Distance"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can consider distance between vectors as the norm of the difference between them. ie: dist(x,y) = ||x-y||"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(8.36779540858881, 0.3872983346207417, 8.532877591996735)"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u,v,w = np.array([1.8,2.0,-3.7,4.7]),np.array([.6,2.1,1.9,-1.4]),np.array([2.0,1.9,-4,4.6])\n",
    "npl.norm(u-v),npl.norm(u-w),npl.norm(v-w) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([5.5, 4], [2, 1])"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#You can use this notion of distance to create a \"nearest neighbor\" function:\n",
    "nearest_neighbor = lambda x,z: z[np.argmin([npl.norm(x-y) for y in z])]\n",
    "z = ([2,1],[7,2],[5.5,4],[4,8],[1,5],[9,6])\n",
    "pointa,pointb = [5,6],[3,3]\n",
    "nearest_neighbor(np.array(pointa),z), nearest_neighbor(np.array(pointb),z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x119e32c88>"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(*zip(*z))\n",
    "n = [str(i) for i in z]\n",
    "for i, txt in enumerate(n):\n",
    "    plt.annotate(txt, (z[i][0], z[i][1]))\n",
    "plt.scatter(pointa[0],pointa[1])\n",
    "plt.scatter(pointb[0],pointb[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.3 Standard Deviation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.6, array([ 0.4, -2.8,  2.4]), -0.0)"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#*this is in the wrong section in the J companion\n",
    "\n",
    "#De-meaning: \n",
    "#useful for understanding how entries of a vector deviate from the mean\n",
    "#also gives us SD in terms of norm\n",
    "de_mean = lambda x: x - np.average(x)\n",
    "x = np.array([1,-2.2,3])\n",
    "np.average(x), de_mean(x), np.average(de_mean(x)).round()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.27182677430029384, 0.27182677430029384)"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Standard deviation is RMS of a de-meaned vector\n",
    "#gives the typical amount that vector values deviate from mean \n",
    "x = np.random.rand(100)\n",
    "stdev = lambda x:npl.norm(x-np.average(x))/np.sqrt(len(x))\n",
    "stdev(x), np.std(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.5019558161617015, 0.593826913848768, -0.0, 1.0)"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "standardize = lambda x: (x - np.average(x)) / rms(x - np.average(x))\n",
    "x = np.random.rand(100)\n",
    "z = standardize(x)\n",
    "np.average(x), rms(x), np.average(z).round(), rms(z)\n",
    "#Taking the average to 0 and RMS to 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.4 Angle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.9689825515916383, 55.51861062801842, array([  0.,   0., 180.]))"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# angle\n",
    "ang = lambda x,y: np.arccos(np.inner(x,y)/(npl.norm(x)*npl.norm(y)))\n",
    "a,b = [1,2,-1],[2,0,-3]\n",
    "ang(a,b), ang(a,b)*(360/(2*np.pi))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.9678196342570433, 11.719700681146525)"
      ]
     },
     "execution_count": 157,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# p value: correlation coefficient is the demeaned version of an angle\n",
    "def correl_coef(a,b):\n",
    "    a_tilde = a - np.average(a)\n",
    "    b_tilde = b - np.average(b)\n",
    "    return ((np.inner(a_tilde, b_tilde))/\n",
    "            (npl.norm(a_tilde)*npl.norm(b_tilde)))\n",
    "\n",
    "a = np.array([4.4,9.4,15.4,12.4,10.4,1.4,-4.6,-5.6,-.6,7.4])\n",
    "b = np.array([6.2,11.2,14.2,14.2,8.2,2.2,-3.8,-4.8,-1.8,4.2])\n",
    "correl_coef(a,b), ang(a,b)*(360/(2*np.pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.5 Complexity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.35 ms ± 274 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "x,y = np.random.rand(10**6), np.random.randn(10**6)\n",
    "%timeit correl_coef(x,y)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
